package com.wolf.cx330.camera

import android.Manifest
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.SurfaceTexture
import android.hardware.camera2.*
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.Size
import android.view.Surface
import android.view.TextureView
import androidx.annotation.RequiresApi
import androidx.annotation.WorkerThread
import androidx.core.app.ActivityCompat
import com.blankj.utilcode.util.ToastUtils
import com.wolf.cx330.R
import com.wolf.cx330.base.BaseActivity
import kotlinx.android.synthetic.main.act_camera.*

/**
 * https://www.jianshu.com/p/067889611ae7
 *
 * Camera教程地址
 */
@RequiresApi(Build.VERSION_CODES.M)
class CameraAct : BaseActivity() {
    private var previewSurfaceTexture: SurfaceTexture? = null
    private var previewSurface: Surface? = null

    //  CameraCharacteristics 是一个只读的相机信息提供者，其内部携带大量的相机信息
    //  相机朝向的 LENS_FACING
    //  判断闪光灯是否可用的 FLASH_INFO_AVAILABLE
    //  获取所有可用 AE 模式的 CONTROL_AE_AVAILABLE_MODES
    //  CameraCharacteristics 以键值对的方式提供相机信息，你可以通过 CameraCharacteristics.get() 方法获取相机信息
    private var frontCameraCharacteristics: CameraCharacteristics? = null
    private var backCameraCharacteristics: CameraCharacteristics? = null
    private var frontCameraId: String? = null
    private var backCameraId: String? = null
    private var captureSession: CameraCaptureSession? = null
    var cameraDevice: CameraDevice? = null

    private val mainHandler = Handler(Looper.getMainLooper())

    //  获取Camera2Manager 示例
    private val cameraManager: CameraManager by lazy { getSystemService(CameraManager::class.java) }


    companion object {
        fun actionStart(context: Context) {
            context.startActivity(Intent(context, CameraAct::class.java))
        }
    }

    @RequiresApi(Build.VERSION_CODES.N)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.act_camera)
        checkPermission {
            initCamera()
            initEvent()
        }
    }


    private fun getCameraInfo(cameraID: String) {
        val cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraID)
        val lensFacing = cameraCharacteristics[CameraCharacteristics.LENS_FACING]
        when (lensFacing) {
            CameraCharacteristics.LENS_FACING_FRONT -> {
                //  前置摄像头
            }
            CameraCharacteristics.LENS_FACING_BACK -> {
                //  后置摄像头
            }
            CameraCharacteristics.LENS_FACING_EXTERNAL -> {
                //  外设摄像头
            }
        }
        //  获取该设备支持的所有预览尺寸
        //  CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP
        val streamConfigurationMap =
            cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
        val supportedSizes = streamConfigurationMap?.getOutputSizes(SurfaceTexture::class.java)
        //  获取设备支持的预览尺寸 需要先从CameraCharacteristics中取出streamConfigurationMap对象
        //  通过streamConfigurationMap.getOutputSizes取出对应类型的尺寸列表,如果不支持 则返回null
        //  常见的类型有 :
        //  ImageReader : 常用来拍照或者接受YUV数据
        //  MediaRecorder : 录制视频
        //  MediaCodec : 录制视频
        //  SurfaceHolder : 显示预览画面
        //  SurfaceTexture : 显示预览画面
        //  这里宽是长边 高是短边 因为相机的Sensor就是如此
        supportedSizes?.forEach { size ->
            println("【IM】CameraAct  getCameraInfo:cameraID = $cameraID width = ${size.width} height = ${size.height}")
        }
    }

    /**
     * 获取到预览尺寸列表后,要根据自己的实际需求过滤出其中一个最符合要求的尺寸,并把它设置给相机;
     */
    @WorkerThread
    private fun getOptimalSize(
        cameraCharacteristics: CameraCharacteristics,
        clazz: Class<*>,
        maxWidth: Int,
        maxHeight: Int
    ): Size? {
        //  宽高比
        val aspectRatio = maxWidth.toFloat() / maxHeight
        //  取出支持的所有预览尺寸
        val streamConfigurationMap =
            cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
        val supportSizes = streamConfigurationMap?.getOutputSizes(clazz)
        supportSizes?.forEach { size ->
            //  当比例相符 且不超出边界时 符合预览条件
//            if ((size.width.toFloat() / size.height == aspectRatio) && size.height <= maxHeight && size.width <= maxWidth) {
            if (size.height <= maxHeight && size.width <= maxWidth) {
                return size
            }
        }
        ToastUtils.showShort("没有合适的预览尺寸")
        return null
    }

    private fun initEvent() {

    }

    /**
     * 打开相机
     */
    var cameraID: String? = null
    private fun openCamera() {
        //  优先选择前置摄像头 其次才是后置摄像头
        cameraID = frontCameraId ?: backCameraId
        if (cameraID != null) {
            if (ActivityCompat.checkSelfPermission(
                    this,
                    Manifest.permission.CAMERA
                ) != PackageManager.PERMISSION_GRANTED
            ) {
                println("【IM】CameraAct  openCamera: 没有相机权限")
                return
            }
            //  打开相机
            cameraManager.openCamera(cameraID!!, object : CameraDevice.StateCallback() {
                override fun onOpened(camera: CameraDevice) {
                    cameraDevice = camera
                    println("【IM】CameraAct  onOpened:")
                }

                override fun onDisconnected(camera: CameraDevice) {
                    println("【IM】CameraAct  onDisconnected: ")
                }

                override fun onError(camera: CameraDevice, error: Int) {
                    camera.close()
                    cameraDevice = null
                    println("【IM】CameraAct  onError: $error")
                }
            }, mainHandler)
        } else {
            ToastUtils.showShort("没有找到对应的相机ID")
        }

    }

    /**
     * 相对的就有关闭相机
     */
    private fun closeCamera() {
        cameraDevice?.close()
    }

    override fun onPause() {
        super.onPause()
        closeCamera()
    }

    @RequiresApi(Build.VERSION_CODES.N)
    private fun initCamera() {

        //  遍历所有可用的摄像头ID
        val cameraIdList = cameraManager.cameraIdList
        //  只取出其中的前置和后置摄像头信息
        cameraIdList.forEach { cameraID ->
            val cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraID)
            if (cameraCharacteristics.isHardwareLevelSupported(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)) {
                if (cameraCharacteristics[CameraCharacteristics.LENS_FACING] == CameraCharacteristics.LENS_FACING_FRONT) {
                    frontCameraId = cameraID
                    frontCameraCharacteristics = cameraCharacteristics
                } else if (cameraCharacteristics[CameraCharacteristics.LENS_FACING] == CameraCharacteristics.LENS_FACING_BACK) {
                    backCameraId = cameraID
                    backCameraCharacteristics = cameraCharacteristics
                }
            }
        }
        openCamera()
        textureView.surfaceTextureListener = PreviewSurfaceTextureListener()
    }

    /**
     * 判断相机得到 HardWareLevel 是否大于等于指定的Level
     */
    @RequiresApi(Build.VERSION_CODES.N)
    private fun CameraCharacteristics.isHardwareLevelSupported(requiredLevel: Int): Boolean {
        val sortedLevels = intArrayOf(
            CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY,
            CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED,
            CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
            CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_3
        )
        val deviceLevel = this[CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL]
        if (requiredLevel == deviceLevel) {
            return true
        }
        for (sortedLevel in sortedLevels) {
            if (requiredLevel == sortedLevel) {
                return true
            }
        }
        return false
    }

    private inner class PreviewSurfaceTextureListener : TextureView.SurfaceTextureListener {
        override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture?, width: Int, height: Int) = Unit

        override fun onSurfaceTextureUpdated(surface: SurfaceTexture?) = Unit

        override fun onSurfaceTextureDestroyed(surface: SurfaceTexture?): Boolean = false

        /**
         * 当 SurfaceTexture 可用的时候会回调onSurfaceTextureAvailable
         * 并且会把SurfaceTexture对象和尺寸传给我们,
         *
         */
        override fun onSurfaceTextureAvailable(surface: SurfaceTexture, width: Int, height: Int) {
            println("【IM】PreviewSurfaceTextureListener  onSurfaceTextureAvailable: width = $width height = $height cameraID = $cameraID  surface = $surface ")
            previewSurfaceTexture = surface
            cameraID?.let { cameraID ->
                val cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraID)
                getOptimalSize(cameraCharacteristics, SurfaceTexture::class.java, width, height)?.let { size ->
                    println("【IM】PreviewSurfaceTextureListener  onSurfaceTextureAvailable:width = ${size.width}  height =  ${size.height}")
                    previewSurfaceTexture?.setDefaultBufferSize(size.width, size.height)
                    previewSurface = Surface(previewSurfaceTexture)
                    //  用于接收预览画面的Surface准备好之后,需要创建一个CameraCaptureSession实例
                    val sessionStateCallback = SessionStateCallback()
                    val outputs = listOf(previewSurface)
                    cameraDevice?.createCaptureSession(outputs, sessionStateCallback, mainHandler)

                }
            }
        }
    }

    private inner class SessionStateCallback : CameraCaptureSession.StateCallback() {
        override fun onConfigureFailed(session: CameraCaptureSession) {

        }

        override fun onConfigured(session: CameraCaptureSession) {
            captureSession = session
            //  创建一个用于预览的CaptureRequest
            val requestBuilder = cameraDevice?.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)!!
            requestBuilder.addTarget(previewSurface!!)
            //  build出一个captureRequest实例
            val request = requestBuilder.build()
            //  开启预览
            captureSession?.setRepeatingRequest(request, RepeatingCaptureStateCallback(), mainHandler)
        }

        override fun onClosed(session: CameraCaptureSession) {
            super.onClosed(session)
            ToastUtils.showShort("onClosed")
        }
    }

    private inner class RepeatingCaptureStateCallback : CameraCaptureSession.CaptureCallback() {
        override fun onCaptureCompleted(session: CameraCaptureSession, request: CaptureRequest, result: TotalCaptureResult) {
            super.onCaptureCompleted(session, request, result)
            println("【IM】RepeatingCaptureStateCallback  onCaptureCompleted: ")
        }

        override fun onCaptureFailed(session: CameraCaptureSession, request: CaptureRequest, failure: CaptureFailure) {
            super.onCaptureFailed(session, request, failure)
            println("【IM】RepeatingCaptureStateCallback  onCaptureFailed: ")
        }

        override fun onCaptureProgressed(session: CameraCaptureSession, request: CaptureRequest, partialResult: CaptureResult) {
            super.onCaptureProgressed(session, request, partialResult)
            println("【IM】RepeatingCaptureStateCallback  onCaptureProgressed: ")
        }

    }


}